#include "server.h"
#include "ui_server.h"

Server::Server(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::Server), mServer(new QTcpServer(this))
{
    ui->setupUi(this);

    connect(mServer, &QTcpServer::newConnection, this, &Server::onNewConnection);

    // 读取配置信息
    QSettings config(APP_DIR + "/config.ini", QSettings::IniFormat);
    ui->editPassword->setText(config.value("Server/Password").toString());
    ui->cbbBlockIP->setChecked(config.value("Server/BlockIP", true).toBool());
}

void Server::closeEvent(QCloseEvent *) {
    // 遍历所有连接的客户端并断开连接
    for(TcpSocket *client : mClients)
        client->client->disconnectFromHost();

    // 写入配置信息
    QSettings config(APP_DIR + "/config.ini", QSettings::IniFormat);
    config.setValue("Server/Password", ui->editPassword->text());
    config.setValue("Server/BlockIP", ui->cbbBlockIP->isChecked());
}

void Server::onNewConnection() {
    QTcpSocket *client = mServer->nextPendingConnection();

    // 如果勾选了禁止其他IP连入，则进行检查
    if(ui->cbbBlockIP->isChecked()) {
        if(client->peerAddress().toIPv4Address() != QHostAddress(ui->editIP->text()).toIPv4Address()) {
            client->disconnectFromHost();
            return;
        }
    }

    {   // 执行事件循环的同时等待接收
        QEventLoop eventLoop;
        bool isForceQuit = false;
        QMetaObject::Connection connectionQuit = connect(client, &QTcpSocket::readyRead, [&eventLoop] { eventLoop.quit(); });
        QObject obj;
        QTimer::singleShot(10000, &obj, [&eventLoop, &isForceQuit] {
            eventLoop.quit();
            isForceQuit = true;
        });
        eventLoop.exec();
        disconnect(connectionQuit);
        if(isForceQuit) {
            client->disconnectFromHost();
            return;
        }
    }

    // 接收客户端发送的第一个数据
    QByteArray array = client->readAll();
    if(array.length() < 32 + 8) {
        client->disconnectFromHost();
        return;
    }
    // 验证Sha256
    QString verify =
            ui->editPassword->text() +
            QString::number(client->peerAddress().toIPv4Address()) +
            QString::number(client->peerPort());
    if(array.mid(8, 32) != Sha256(verify.toUtf8())) {
        client->disconnectFromHost();
        return;
    }

    // 得到客户端名字（第一个数据除去前32 + 8字节）
    QString name = array.right(array.length() - 32 - 8).trimmed();

    // 创建Item和Widget
    QListWidgetItem *item = new QListWidgetItem;
    ClientInfo *widget = new ClientInfo(
                name.isEmpty()
                ? QString("%1:%2").arg(client->peerAddress().toString()).arg(client->peerPort())
                : QString("%1\n%2:%3").arg(name).arg(client->peerAddress().toString()).arg(client->peerPort())
                );
    // 调整Item大小属性
    widget->adjustSize();
    item->setSizeHint(QSize(1, widget->height()));
    item->setFlags(Qt::ItemIsEnabled);
    // 向listWidget添加Item
    ui->listWidget->insertItem(0, item);
    ui->listWidget->setItemWidget(item, widget);

    // 将该客户端加入 mCients中
    TcpSocket *socket = new TcpSocket(client, widget, ui->listWidgetFiles);
    mClients << socket;

    // 当“断开”按钮按下时断开连接
    connect(widget, &ClientInfo::disconnectRequested, [client] {
        client->disconnectFromHost();
    });
    // 当断开连接时进行对应的操作
    connect(client, &QTcpSocket::disconnected, [this, item, widget, socket] {
        // 将该客户端从mClients中移除
        mClients.removeOne(socket);
        socket->deleteLater();

        // 移除控件
        ui->listWidget->removeItemWidget(item);
        widget->deleteLater();
        ui->listWidget->takeItem(ui->listWidget->row(item));
        delete item;
    });

    // 初始化客户端文件列表
    socket->writeFileList("");
}

void Server::on_btnBound_clicked() {
    // 如果服务端isListening，则解绑
    if(mServer->isListening()) {
        for(TcpSocket *socket : mClients)
            socket->client->disconnectFromHost();
        mClients.clear();
        mServer->close();
        ui->editIP->setText("");
        ui->editPort->setText("");
        ui->btnBound->setText("绑定");
        return;
    }

    // 绑定IP和端口
    if(!mServer->listen()) {
        QMessageBox::critical(this, "错误", QString("绑定失败: %1").arg(mServer->errorString()));
        return;
    }

    // 得到绑定的IP和端口
    QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
    QHostAddress address;
    for(const QHostAddress &one : addresses) {
        if(one != QHostAddress::LocalHost && one.toIPv4Address()) {
            address = one;
            break;
        }
    }
    if(address.isNull())
        address = QHostAddress(QHostAddress::LocalHost);

    // 显示IP和端口信息
    ui->editIP->setText(address.toString());
    ui->editPort->setText(QString::number(mServer->serverPort()));
    ui->btnBound->setText("解绑");
}
void Server::on_btnDisconnect_clicked()
{
    for(TcpSocket *socket :mClients)
        socket->client->disconnectFromHost();
}
